{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from IPython.core.display import HTML\n",
    "from itertools import chain\n",
    "from collections import Counter, defaultdict, namedtuple, OrderedDict\n",
    "from pomegranate import State, HiddenMarkovModel, DiscreteDistribution\n",
    "import os\n",
    "from io import BytesIO\n",
    "from itertools import chain\n",
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "Sentence = namedtuple(\"Sentence\", \"words tags\")\n",
    "\n",
    "def read_data(filename):\n",
    "    \"\"\"Read tagged sentence data\"\"\"\n",
    "    with open(filename, 'r') as f:\n",
    "        sentence_lines = [l.split(\"\\n\") for l in f.read().split(\"\\n\\n\")]\n",
    "    return OrderedDict(((s[0], Sentence(*zip(*[l.strip().split(\"\\t\")\n",
    "                        for l in s[1:]]))) for s in sentence_lines if s[0]))\n",
    "\n",
    "\n",
    "def read_tags(filename):\n",
    "    \"\"\"Read a list of word tag classes\"\"\"\n",
    "    with open(filename, 'r') as f:\n",
    "        tags = f.read().split(\"\\n\")\n",
    "    return frozenset(tags)\n",
    "\n",
    "Sentence = namedtuple(\"Sentence\", \"words tags\")\n",
    "\n",
    "def read_data(filename):\n",
    "    \"\"\"Read tagged sentence data\"\"\"\n",
    "    with open(filename, 'r') as f:\n",
    "        sentence_lines = [l.split(\"\\n\") for l in f.read().split(\"\\n\\n\")]\n",
    "    return OrderedDict(((s[0], Sentence(*zip(*[l.strip().split(\"\\t\")\n",
    "                        for l in s[1:]]))) for s in sentence_lines if s[0]))\n",
    "\n",
    "def read_tags(filename):\n",
    "    \"\"\"Read a list of word tag classes\"\"\"\n",
    "    with open(filename, 'r') as f:\n",
    "        tags = f.read().split(\"\\n\")\n",
    "    return frozenset(tags)\n",
    "\n",
    "class Subset(namedtuple(\"BaseSet\", \"sentences keys vocab X tagset Y N stream\")):\n",
    "    def __new__(cls, sentences, keys):\n",
    "        word_sequences = tuple([sentences[k].words for k in keys])\n",
    "        tag_sequences = tuple([sentences[k].tags for k in keys])\n",
    "        wordset = frozenset(chain(*word_sequences))\n",
    "        tagset = frozenset(chain(*tag_sequences))\n",
    "        N = sum(1 for _ in chain(*(sentences[k].words for k in keys)))\n",
    "        stream = tuple(zip(chain(*word_sequences), chain(*tag_sequences)))\n",
    "        return super().__new__(cls, {k: sentences[k] for k in keys}, keys, wordset, word_sequences,\n",
    "                               tagset, tag_sequences, N, stream.__iter__)\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.sentences)\n",
    "\n",
    "    def __iter__(self):\n",
    "        return iter(self.sentences.items())\n",
    "\n",
    "\n",
    "class Dataset(namedtuple(\"_Dataset\", \"sentences keys vocab X tagset Y training_set testing_set N stream\")):\n",
    "    def __new__(cls, tagfile, datafile, train_test_split=0.8, seed=112890):\n",
    "        tagset = read_tags(tagfile)\n",
    "        sentences = read_data(datafile)\n",
    "        keys = tuple(sentences.keys())\n",
    "        wordset = frozenset(chain(*[s.words for s in sentences.values()]))\n",
    "        word_sequences = tuple([sentences[k].words for k in keys])\n",
    "        tag_sequences = tuple([sentences[k].tags for k in keys])\n",
    "        N = sum(1 for _ in chain(*(s.words for s in sentences.values())))\n",
    "        \n",
    "        # split data into train/test sets\n",
    "        _keys = list(keys)\n",
    "        if seed is not None: random.seed(seed)\n",
    "        random.shuffle(_keys)\n",
    "        split = int(train_test_split * len(_keys))\n",
    "        training_data = Subset(sentences, _keys[:split])\n",
    "        testing_data = Subset(sentences, _keys[split:])\n",
    "        stream = tuple(zip(chain(*word_sequences), chain(*tag_sequences)))\n",
    "        return super().__new__(cls, dict(sentences), keys, wordset, word_sequences, tagset,\n",
    "                               tag_sequences, training_data, testing_data, N, stream.__iter__)\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.sentences)\n",
    "\n",
    "    def __iter__(self):\n",
    "        return iter(self.sentences.items())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "There are 57340 sentences in the corpus.\n",
      "There are 45872 sentences in the training set.\n",
      "There are 11468 sentences in the testing set.\n"
     ]
    }
   ],
   "source": [
    "data = Dataset(\"tags-universal.txt\", \"brown-universal.txt\", train_test_split=0.8)\n",
    "\n",
    "print(\"There are {} sentences in the corpus.\".format(len(data)))\n",
    "print(\"There are {} sentences in the training set.\".format(len(data.training_set)))\n",
    "print(\"There are {} sentences in the testing set.\".format(len(data.testing_set)))\n",
    "\n",
    "assert len(data) == len(data.training_set) + len(data.testing_set), \\\n",
    "       \"The number of sentences in the training set + testing set should sum to the number of sentences in the corpus\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sentence: b100-38532\n",
      "words:\n",
      "\t('Perhaps', 'it', 'was', 'right', ';', ';')\n",
      "tags:\n",
      "\t('ADV', 'PRON', 'VERB', 'ADJ', '.', '.')\n"
     ]
    }
   ],
   "source": [
    "key = 'b100-38532'\n",
    "print(\"Sentence: {}\".format(key))\n",
    "print(\"words:\\n\\t{!s}\".format(data.sentences[key].words))\n",
    "print(\"tags:\\n\\t{!s}\".format(data.sentences[key].tags))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "There are a total of 1161192 samples of 56057 unique words in the corpus.\n",
      "There are 928458 samples of 50536 unique words in the training set.\n",
      "There are 232734 samples of 25112 unique words in the testing set.\n",
      "There are 5521 words in the test set that are missing in the training set.\n"
     ]
    }
   ],
   "source": [
    "print(\"There are a total of {} samples of {} unique words in the corpus.\"\n",
    "      .format(data.N, len(data.vocab)))\n",
    "print(\"There are {} samples of {} unique words in the training set.\"\n",
    "      .format(data.training_set.N, len(data.training_set.vocab)))\n",
    "print(\"There are {} samples of {} unique words in the testing set.\"\n",
    "      .format(data.testing_set.N, len(data.testing_set.vocab)))\n",
    "print(\"There are {} words in the test set that are missing in the training set.\"\n",
    "      .format(len(data.testing_set.vocab - data.training_set.vocab)))\n",
    "\n",
    "assert data.N == data.training_set.N + data.testing_set.N, \\\n",
    "       \"The number of training + test samples should sum to the total number of samples\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sentence 1: ('Mr.', 'Podger', 'had', 'thanked', 'him', 'gravely', ',', 'and', 'now', 'he', 'made', 'use', 'of', 'the', 'advice', '.')\n",
      "\n",
      "Labels 1: ('NOUN', 'NOUN', 'VERB', 'VERB', 'PRON', 'ADV', '.', 'CONJ', 'ADV', 'PRON', 'VERB', 'NOUN', 'ADP', 'DET', 'NOUN', '.')\n",
      "\n",
      "Sentence 2: ('But', 'there', 'seemed', 'to', 'be', 'some', 'difference', 'of', 'opinion', 'as', 'to', 'how', 'far', 'the', 'board', 'should', 'go', ',', 'and', 'whose', 'advice', 'it', 'should', 'follow', '.')\n",
      "\n",
      "Labels 2: ('CONJ', 'PRT', 'VERB', 'PRT', 'VERB', 'DET', 'NOUN', 'ADP', 'NOUN', 'ADP', 'ADP', 'ADV', 'ADV', 'DET', 'NOUN', 'VERB', 'VERB', '.', 'CONJ', 'DET', 'NOUN', 'PRON', 'VERB', 'VERB', '.')\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# accessing words with Dataset.X and tags with Dataset.Y \n",
    "for i in range(2):    \n",
    "    print(\"Sentence {}:\".format(i + 1), data.X[i])\n",
    "    print()\n",
    "    print(\"Labels {}:\".format(i + 1), data.Y[i])\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Stream (word, tag) pairs:\n",
      "\n",
      "\t ('Mr.', 'NOUN')\n",
      "\t ('Podger', 'NOUN')\n",
      "\t ('had', 'VERB')\n",
      "\t ('thanked', 'VERB')\n",
      "\t ('him', 'PRON')\n"
     ]
    }
   ],
   "source": [
    "# use Dataset.stream() (word, tag) samples for the entire corpus\n",
    "print(\"\\nStream (word, tag) pairs:\\n\")\n",
    "for i, pair in enumerate(data.stream()):\n",
    "    print(\"\\t\", pair)\n",
    "    if i > 3: break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Build a Most Frequent Class tagger\n",
    "\n",
    "### IMPLEMENTATION: Pair Counts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pair_counts(tags, words):\n",
    "    d = defaultdict(lambda: defaultdict(int))\n",
    "    for tag, word in zip(tags, words):\n",
    "        d[tag][word] += 1\n",
    "        \n",
    "    return d\n",
    "tags = [tag for i, (word, tag) in enumerate(data.training_set.stream())]\n",
    "words = [word for i, (word, tag) in enumerate(data.training_set.stream())]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### IMPLEMENTATION: Most Frequent Class Tagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "FakeState = namedtuple('FakeState', 'name')\n",
    "\n",
    "class MFCTagger:\n",
    "    missing = FakeState(name = '<MISSING>')\n",
    "    \n",
    "    def __init__(self, table):\n",
    "        self.table = defaultdict(lambda: MFCTagger.missing)\n",
    "        self.table.update({word: FakeState(name=tag) for word, tag in table.items()})\n",
    "        \n",
    "    def viterbi(self, seq):\n",
    "        \"\"\"This method simplifies predictions by matching the Pomegranate viterbi() interface\"\"\"\n",
    "        return 0., list(enumerate([\"<start>\"] + [self.table[w] for w in seq] + [\"<end>\"]))\n",
    "    \n",
    "tags = [tag for i, (word, tag) in enumerate(data.training_set.stream())]\n",
    "words = [word for i, (word, tag) in enumerate(data.training_set.stream())]\n",
    "\n",
    "word_counts = pair_counts(words, tags)\n",
    "mfc_table = dict((word, max(tags.keys(), key=lambda key: tags[key])) for word, tags in word_counts.items())\n",
    "\n",
    "mfc_model = MFCTagger(mfc_table)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Making Predictions with a Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def replace_unknown(sequence):\n",
    "    \n",
    "    return [w if w in data.training_set.vocab else 'nan' for w in sequence]\n",
    "\n",
    "def simplify_decoding(X, model):\n",
    "    \n",
    "    _, state_path = model.viterbi(replace_unknown(X))\n",
    "    return [state[1].name for state in state_path[1:-1]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example Decoding Sequences with MFC Tagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sentence Key: b100-28144\n",
      "\n",
      "Predicted labels:\n",
      "-----------------\n",
      "['CONJ', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'CONJ', 'NOUN', 'NUM', '.', '.', 'NOUN', '.', '.']\n",
      "\n",
      "Actual labels:\n",
      "--------------\n",
      "('CONJ', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'CONJ', 'NOUN', 'NUM', '.', '.', 'NOUN', '.', '.')\n",
      "\n",
      "\n",
      "Sentence Key: b100-23146\n",
      "\n",
      "Predicted labels:\n",
      "-----------------\n",
      "['PRON', 'VERB', 'DET', 'NOUN', 'ADP', 'ADJ', 'ADJ', 'NOUN', 'VERB', 'VERB', '.', 'ADP', 'VERB', 'DET', 'NOUN', 'ADP', 'NOUN', 'ADP', 'DET', 'NOUN', '.']\n",
      "\n",
      "Actual labels:\n",
      "--------------\n",
      "('PRON', 'VERB', 'DET', 'NOUN', 'ADP', 'ADJ', 'ADJ', 'NOUN', 'VERB', 'VERB', '.', 'ADP', 'VERB', 'DET', 'NOUN', 'ADP', 'NOUN', 'ADP', 'DET', 'NOUN', '.')\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for key in data.testing_set.keys[:2]:\n",
    "    print(\"Sentence Key: {}\\n\".format(key))\n",
    "    print(\"Predicted labels:\\n-----------------\")\n",
    "    print(simplify_decoding(data.sentences[key].words, mfc_model))\n",
    "    print()\n",
    "    print(\"Actual labels:\\n--------------\")\n",
    "    print(data.sentences[key].tags)\n",
    "    print(\"\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Evaluating Model Accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def accuracy(X, Y, model):\n",
    "    \n",
    "    correct = total_predictions = 0\n",
    "    for observations, actual_tags in zip(X, Y):\n",
    "        \n",
    "        # The model.viterbi call in simplify_decoding will return None if the HMM\n",
    "        # raises an error (for example, if a test sentence contains a word that\n",
    "        # is out of vocabulary for the training set). Any exception counts the\n",
    "        # full sentence as an error (which makes this a conservative estimate).\n",
    "        try:\n",
    "            most_likely_tags = simplify_decoding(observations, model)\n",
    "            correct += sum(p == t for p, t in zip(most_likely_tags, actual_tags))\n",
    "        except:\n",
    "            pass\n",
    "        total_predictions += len(observations)\n",
    "    return correct / total_predictions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Evaluate the accuracy of the MFC tagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training accuracy mfc_model: 95.72%\n",
      "testing accuracy mfc_model: 93.01%\n"
     ]
    }
   ],
   "source": [
    "mfc_training_acc = accuracy(data.training_set.X, data.training_set.Y, mfc_model)\n",
    "print(\"training accuracy mfc_model: {:.2f}%\".format(100 * mfc_training_acc))\n",
    "\n",
    "mfc_testing_acc = accuracy(data.testing_set.X, data.testing_set.Y, mfc_model)\n",
    "print(\"testing accuracy mfc_model: {:.2f}%\".format(100 * mfc_testing_acc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build an HMM tagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def unigram_counts(sequences):\n",
    "\n",
    "    return Counter(sequences)\n",
    "\n",
    "tags = [tag for i, (word, tag) in enumerate(data.training_set.stream())]\n",
    "tag_unigrams = unigram_counts(tags)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### IMPLEMENTATION: Bigram Counts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def bigram_counts(sequences):\n",
    "\n",
    "    d = Counter(sequences)\n",
    "    return d\n",
    "\n",
    "tags = [tag for i, (word, tag) in enumerate(data.stream())]\n",
    "o = [(tags[i],tags[i+1]) for i in range(0,len(tags)-2,2)]\n",
    "tag_bigrams = bigram_counts(o)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### IMPLEMENTATION: Sequence Starting Counts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def starting_counts(sequences):\n",
    "    \n",
    "    d = Counter(sequences)\n",
    "    return d\n",
    "\n",
    "tags = [tag for i, (word, tag) in enumerate(data.stream())]\n",
    "starts_tag = [i[0] for i in data.Y]\n",
    "tag_starts = starting_counts(starts_tag)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### IMPLEMENTATION: Sequence Ending Counts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ending_counts(sequences):\n",
    "    \n",
    "    d = Counter(sequences)\n",
    "    return d\n",
    "\n",
    "end_tag = [i[len(i)-1] for i in data.Y]\n",
    "tag_ends = ending_counts(end_tag)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### IMPLEMENTATION: Basic HMM Tagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "basic_model = HiddenMarkovModel(name=\"base-hmm-tagger\")\n",
    "\n",
    "tags = [tag for i, (word, tag) in enumerate(data.stream())]\n",
    "words = [word for i, (word, tag) in enumerate(data.stream())]\n",
    "\n",
    "tags_count=unigram_counts(tags)\n",
    "tag_words_count=pair_counts(tags,words)\n",
    "\n",
    "starting_tag_list=[i[0] for i in data.Y]\n",
    "ending_tag_list=[i[-1] for i in data.Y]\n",
    "\n",
    "starting_tag_count=starting_counts(starting_tag_list)#the number of times a tag occured at the start\n",
    "ending_tag_count=ending_counts(ending_tag_list)      #the number of times a tag occured at the end\n",
    "\n",
    "\n",
    "\n",
    "to_pass_states = []\n",
    "for tag, words_dict in tag_words_count.items():\n",
    "    total = float(sum(words_dict.values()))\n",
    "    distribution = {word: count/total for word, count in words_dict.items()}\n",
    "    tag_emissions = DiscreteDistribution(distribution)\n",
    "    tag_state = State(tag_emissions, name=tag)\n",
    "    to_pass_states.append(tag_state)\n",
    "\n",
    "\n",
    "basic_model.add_states()    \n",
    "    \n",
    "\n",
    "start_prob={}\n",
    "\n",
    "for tag in tags:\n",
    "    start_prob[tag]=starting_tag_count[tag]/tags_count[tag]\n",
    "\n",
    "for tag_state in to_pass_states :\n",
    "    basic_model.add_transition(basic_model.start,tag_state,start_prob[tag_state.name])    \n",
    "\n",
    "end_prob={}\n",
    "\n",
    "for tag in tags:\n",
    "    end_prob[tag]=ending_tag_count[tag]/tags_count[tag]\n",
    "for tag_state in to_pass_states :\n",
    "    basic_model.add_transition(tag_state,basic_model.end,end_prob[tag_state.name])\n",
    "    \n",
    "\n",
    "\n",
    "transition_prob_pair={}\n",
    "\n",
    "for key in tag_bigrams.keys():\n",
    "    transition_prob_pair[key]=tag_bigrams.get(key)/tags_count[key[0]]\n",
    "for tag_state in to_pass_states :\n",
    "    for next_tag_state in to_pass_states :\n",
    "        basic_model.add_transition(tag_state,next_tag_state,transition_prob_pair[(tag_state.name,next_tag_state.name)])\n",
    "\n",
    "basic_model.bake()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training accuracy basic hmm model: 97.49%\n",
      "testing accuracy basic hmm model: 96.09%\n"
     ]
    }
   ],
   "source": [
    "hmm_training_acc = accuracy(data.training_set.X, data.training_set.Y, basic_model)\n",
    "print(\"training accuracy basic hmm model: {:.2f}%\".format(100 * hmm_training_acc))\n",
    "\n",
    "hmm_testing_acc = accuracy(data.testing_set.X, data.testing_set.Y, basic_model)\n",
    "print(\"testing accuracy basic hmm model: {:.2f}%\".format(100 * hmm_testing_acc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example Decoding Sequences with the HMM Tagger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sentence Key: b100-28144\n",
      "\n",
      "Predicted labels:\n",
      "-----------------\n",
      "['CONJ', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'CONJ', 'NOUN', 'NUM', '.', '.', 'NOUN', '.', '.']\n",
      "\n",
      "Actual labels:\n",
      "--------------\n",
      "('CONJ', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'NOUN', 'NUM', '.', 'CONJ', 'NOUN', 'NUM', '.', '.', 'NOUN', '.', '.')\n",
      "\n",
      "\n",
      "Sentence Key: b100-23146\n",
      "\n",
      "Predicted labels:\n",
      "-----------------\n",
      "['PRON', 'VERB', 'DET', 'NOUN', 'ADP', 'ADJ', 'ADJ', 'NOUN', 'VERB', 'VERB', '.', 'ADP', 'VERB', 'DET', 'NOUN', 'ADP', 'NOUN', 'ADP', 'DET', 'NOUN', '.']\n",
      "\n",
      "Actual labels:\n",
      "--------------\n",
      "('PRON', 'VERB', 'DET', 'NOUN', 'ADP', 'ADJ', 'ADJ', 'NOUN', 'VERB', 'VERB', '.', 'ADP', 'VERB', 'DET', 'NOUN', 'ADP', 'NOUN', 'ADP', 'DET', 'NOUN', '.')\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for key in data.testing_set.keys[:2]:\n",
    "    print(\"Sentence Key: {}\\n\".format(key))\n",
    "    print(\"Predicted labels:\\n-----------------\")\n",
    "    print(simplify_decoding(data.sentences[key].words, basic_model))\n",
    "    print()\n",
    "    print(\"Actual labels:\\n--------------\")\n",
    "    print(data.sentences[key].tags)\n",
    "    print(\"\\n\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
